package at.ac.tuwien.prog.command;

import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import at.ac.tuwien.prog.entity.Register;
import at.ac.tuwien.prog.flash.IFlashManager;
import at.ac.tuwien.prog.memory.IMemoryManager;
import at.ac.tuwien.prog.system.ISystem;

/**
 * 
 * Lies einen Block aus dem Flash in einen aus 128 aufeinanderfolgenden Registern bestehenden Puffer,
 * wobei B die konstante Adresse des Puffers und A die Adresse eines Registers ist,
 * dessen Inhalt die Nummer des gelesenen Blocks im Flash angibt.
 * 
 * @author christoph.pickl@student.tuwien.ac.at
 */
public class FlashReadCommand extends AbstractCommand {
	
	private static final Log LOG = LogFactory.getLog(FlashReadCommand.class);

	public static final String NAME = "flashr";
	

	public FlashReadCommand(int flashReadBlockNumberAddress, int targetBufferAddress) {
		super(flashReadBlockNumberAddress, targetBufferAddress);
		// TODO Auto-generated constructor stub
	}

	public void execute(ISystem system) {
		final int flashReadBlockNumberAddress = this.getOperand1();
		final int targetBufferAddress = this.getOperand2();
		LOG.info("execute(flashReadBlockNumberAddress="+flashReadBlockNumberAddress+"; targetBufferAddress="+targetBufferAddress+")");
		
		final IMemoryManager memory = system.getMemoryManager();
		final IFlashManager flash = system.getFlashManager();
		
		final Register reflashReadBlockNumber = memory.getRegisterValue(flashReadBlockNumberAddress);
		byte[] flashData;
		try {
			flashData = flash.readBlock(reflashReadBlockNumber.getIntValue());
		} catch (IOException e) {
			throw new RuntimeException("Flash read error!", e);
		}
		
		// only process 128 (32 ints, each 4 byte) out of 512 bytes and save to memory
		int currentTargetBufferAddress = targetBufferAddress;
		for (int i = 0; i < 128; i++) {
			final byte[] resultBytes = new byte[4];
			for (int b = 0; b < 4; b++) {
				resultBytes[b] = flashData[i * 4 + b];
			}
			final Register result = Register.newByBytes(resultBytes);
			
//			LOG.trace((i+1) + ". flash read: " + result);
			memory.setRegisterValue(currentTargetBufferAddress, result);
			currentTargetBufferAddress++;
		}
	}

}
